home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 001-100 / 001-025 / 003 / ff / filter.c < prev    next >
C/C++ Source or Header  |  1995-03-17  |  5KB  |  186 lines

  1. /*
  2.     Function:    filter "Filter Command Line Files In Classic UNIX Style"
  3.     Created:     Sat Aug 10 21:57:12 EDT 1985
  4.     By:          Gary Perlman (Wang Institute, Tyngsboro, MA 01879 USA)
  5.     Compilation: nothing unusual
  6.     Tester:      $Compile: cc -DSTANDALONE -o filter %f
  7.     Preconditions:
  8.         The index of the first file operand has been determined.
  9.     Postconditions:
  10.         All files have been opened, processed, and closed.
  11.     Returns:
  12.         The return status (non-zero is bad) depends on the accessibility
  13.         of files, the ability to open them, and the return statuses of
  14.         the called function.
  15.     Exceptions:
  16.         If any file cannot be accessed, then none will be processed.
  17.         During processing, if something goes wrong (a file that could
  18.         be accessed cannot be opened, or the file processor returns a
  19.         non-zero status), processing continues.
  20.     Notes:
  21.         "-" is the conventional name for the standard input.
  22.             It can only be read once.
  23.         Fputs and putc are used to print error messages to avoid
  24.             loading fat fprintf just because filter used it.
  25. */
  26.  
  27.  
  28. #include <stdio.h>
  29.  
  30. #ifdef STANDALONE
  31.  
  32. int
  33. cat (file, ioptr)
  34. char    *file;
  35. register    FILE    *ioptr;
  36.     {
  37.     register    int     C;
  38.     while ((C = getc (ioptr)) != EOF)
  39.         putchar (C);
  40.     return (0);
  41.     }
  42.  
  43. main (argc, argv) char **argv;
  44.     {
  45.     int     cat ();
  46.  
  47.     if (filter (argc, argv, 1, cat))
  48.         {
  49.         putc ('\007', stderr); /* UNIX friendly error message */
  50.         exit (1);
  51.         }
  52.     exit (0);
  53.     }
  54.  
  55. #endif STANDALONE
  56.  
  57.  
  58. /* LINTLIBRARY */
  59. static
  60. void
  61. errmsg (pgm, file, errorno, dflt)
  62. char    *pgm;       /* name of the program running */
  63. char    *file;      /* file operand to be mentioned (if any) */
  64. int     errorno;    /* system errno or some bad value */
  65. char    *dflt;      /* default message for bad error numbers */
  66.     {
  67. #ifdef unix
  68.     extern    char *sys_errlist[];  /* list of error messages */
  69.     extern    int sys_nerr;         /* number of error messages */
  70. #endif
  71.  
  72.     fputs (pgm, stderr);
  73.     putc (':', stderr);
  74.     putc (' ', stderr);
  75. #ifdef unix
  76.     if (errorno > 0 && errorno < sys_nerr)
  77.         fputs (sys_errlist[errorno], stderr);
  78.     else
  79.         fputs (dflt, stderr);
  80. #else
  81.     fputs ("<unknown error>", stderr);
  82. #endif
  83.     if (file)
  84.         {
  85.         putc (' ', stderr);
  86.         putc ('\'', stderr);
  87.         fputs (file, stderr);
  88.         putc ('\'', stderr);
  89.         }
  90.     putc ('\n', stderr);
  91.     }
  92.  
  93.  
  94. #define    isstdin(file) (file[0] == '-' && file[1] == '\0')
  95.  
  96. int
  97. filter (argc, argv, curarg, process)
  98. int     argc;          /* real number of command line args */
  99. char    **argv;        /* command line argument pointer */
  100. int     curarg;        /* first argv to filter */
  101. int     (*process) (); /* status process (char *name, FILE *ioptr) */
  102.     {
  103.     int     status = 0;         /* return status of this function */
  104.     int     arg;                /* loop index variable */
  105.     char    *file;              /* name of the current file */
  106.     char    *pgm = argv[0];     /* name of the program */
  107.     FILE    *ioptr;             /* file pointer for opening */
  108.     int     countstdin = 0;     /* number of times stdin is processed */
  109.     extern    int errno;          /* system error number */
  110.  
  111.     if (curarg == argc)
  112.         status += ((*process) ("-", stdin));
  113.     else
  114.         {
  115.         /* first check to make sure all files can be opened to read */
  116.         for (arg = curarg; arg < argc; arg++)
  117.             {
  118.             file = argv[arg];
  119.             if (isstdin (file))
  120.                 countstdin++;
  121.             else if (!readable (file))
  122.                 {
  123.                 errmsg (pgm, file, errno, "Can't access file");
  124.                 status++;
  125.                 }
  126.             }
  127.         if (countstdin > 1)
  128.             {
  129.             errmsg (pgm, NULL, -1, "Can only read standard input once");
  130.             status++;
  131.             }
  132.         if (status == 0)
  133.             for (arg = curarg; arg < argc; arg++)
  134.                 {
  135.                 file = argv[arg];
  136.                 if (isstdin (file))
  137.                     status += ((*process) (file, stdin) != 0);
  138.                 else if (ioptr = fopen (file, "r"))
  139.                     {
  140.                     status += ((*process) (file, ioptr) != 0);
  141.                     (void) fclose (ioptr);
  142.                     }
  143.                 else
  144.                     {
  145.                     errmsg (pgm, file, errno, "Can't open file");
  146.                     status++;
  147.                     }
  148.                 }
  149.         }
  150.     return (status);
  151.     }
  152.  
  153. /*NOTES
  154.     Some modifications might be useful but unpopular:
  155.         If there is piped input (!isatty (fileno (stdin))),
  156.         and the standard input is not read,
  157.         then some information may be ignored,
  158.         so a warning should be printed.
  159.         Unfortunately, this would break things like vi filters.
  160.  
  161.         If there is not piped input,
  162.         and the standard input is being read from the keyboard,
  163.         then prompt the user for input with something like:
  164.             pgm: reading input from terminal
  165.         This would avoid the problem of people forgetting to supply
  166.         an input redirection.
  167. */
  168.  
  169. readable (file)
  170. char *file;
  171. {
  172. #ifdef AMIGA
  173.     int status = 0;
  174.     FILE *fp;
  175.  
  176.     fp = fopen (file, "r");
  177.     if (fp != NULL) {
  178.         status = 1;
  179.     }
  180.     fclose (fp);
  181.     return (status);
  182. #else
  183.     return (!access (file, 4));
  184. #endif
  185. }
  186.